package cn.sh.tools.annotation;

import cn.sh.tools.domain.ShContext;
import cn.sh.tools.util.IdUtils;
import cn.sh.tools.util.ThreadLocalUtils;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @author shihao
 * @description 日志切面
 */
@Aspect
@Component
@Slf4j
public class TimeAspect {

    @Pointcut("@annotation(cn.sh.tools.annotation.TimeConsume)")
    private void time() {
    }

    @Before(value = "time()")
    public void before(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if (method.isAnnotationPresent(TimeConsume.class)) {
            ShContext shContext = new ShContext();
            shContext.setId(IdUtils.getSnowflakeNextIdStr());
            shContext.setStopwatch(Stopwatch.createStarted());
            ThreadLocalUtils.setShContext(shContext);

            log.info("[{}]-[{}]开始计时",
                    method.getDeclaringClass().getName().concat("#").concat(method.getName()),
                    shContext.getId());
        }
    }

    @After(value = "time()")
    public void after(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if (method.isAnnotationPresent(TimeConsume.class)) {
            ShContext shContext = ThreadLocalUtils.getShContext();
            log.info("[{}]-[{}]耗时: {} ms",
                    method.getDeclaringClass().getName().concat("#").concat(method.getName()),
                    shContext.getId(),
                    shContext.getStopwatch().elapsed(TimeUnit.MILLISECONDS));
            ThreadLocalUtils.removeShContext();
        }
    }

}
